//
//  CheckItemViewModel.m
//  MobileChecker
//
//  Created by Lymons on 15-1-5.
//  Copyright (c) 2015年 Lymons. All rights reserved.
//

#import "CheckAutoItemViewModel.h"
#import "CheckResultUserDefaults.h"
#import "AppDelegate.h"
#import "Steps.h"
#import "HUDHelper.h"
#import "CustomizedProgressHUD.h"


@interface HUDHelper (CheckAutoItemViewModel)

- (void)showHUD:(NSString *)title message:(NSString *)message yOffset:(CGFloat)offset;

@end

@interface CheckAutoItemViewModel ()

@property (nonatomic) NSArray *itemsHeaderString;
@property (nonatomic) RACDisposable *luminaDispose;

@end

@implementation CheckAutoItemViewModel

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.hideMonitor = YES;
        self.items = @[@"WIFI",
                       @"Bluetooth",
//                       @"GPS",
                       @"ジャイロ",
                       @"磁気",
                       @"近接",
                       @"輝度",];
        [self resetItemsResult];
        self.itemsHeaderString = @[@"WIFI通信の診断を行います。\n機内モードをオフにしてください。",
                                   @"Bluetoohの診断を行います。\n機内モードをオフにしてください。",
//                                   @"GPS、ジャイロ、磁気センサーの診断を行います。端末を傾けたり、左右に動かしてください。",
                                   @"ジャイロ、磁気センサーの診断を行います。端末を傾けたり、左右に動かしてください。",
                                   @"ジャイロ、磁気センサーの診断を行います。端末を傾けたり、左右に動かしてください。",
                                   @"近接、輝度センサーの診断を行います。ディスプレーの前に手をかざしたりし、光度を確認してください。",
                                   @"近接、輝度センサーの診断を行います。ディスプレーの前に手をかざしたりし、光度を確認してください。",
                                   @"自動診断は正常に終了しました。\n「次へ」ボタンを押してください。"];
        self.headerString = [self.itemsHeaderString objectAtIndex:0];
        
//        RACSignal *foregroundSignal = [[NSNotificationCenter defaultCenter] rac_addObserverForName:NEED_START_AUTO_CHECK object:nil];
//        @weakify(self);
//        [foregroundSignal subscribeNext:^(id x) {
//            @strongify(self);
//            [self startCheck];
//        }];
    }
    return self;
}

- (AutoCheckService *)service
{
    if (_service == nil) {
        _service = [[AutoCheckService alloc] init];
    }
    return _service;
}

- (void)startCheck
{
//    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
    
    self.checkCompleted = NO;
    [CheckResultUserDefaults standardUserDefaults].wifi3gCheckResult = DiagnosisCheckResultNoCheck;
    [CheckResultUserDefaults standardUserDefaults].bluetoothCheckResult = DiagnosisCheckResultNoCheck;
    [CheckResultUserDefaults standardUserDefaults].gpsCheckResult = DiagnosisCheckResultNoCheck;
    @weakify(self);
    [Steps syncWithBeforeBlock:^BOOL(NSUInteger currentStep, NSString *stepName) {
        @strongify(self);
        self.headerString = [self.itemsHeaderString objectAtIndex:currentStep];
        if ((currentStep < self.itemsResult.count)) {
            [self.itemsResult replaceObjectAtIndex:currentStep withObject:ITEM_RESULT_CHECKING];
        }
        return !self.checkCompleted;
    } array:@[^(Steps *leftSteps){
        // WIFI、３G通信の診断を行います。
        RACSignal *signal = [self handleSignal:[self.service networkCheckSignal:leftSteps] errorMsg:@"機内モードをオフにしてください。またはインターネットに繋がられるネットワークを選択してください。"];
        [self handleErrorSignal:signal];
        [[self commonSinal:signal stepNumber:leftSteps.stepNumber] subscribeNext:^(NSNumber *result) {
            [CheckResultUserDefaults standardUserDefaults].wifi3gCheckResult = [result integerValue];
        }];
    },^(Steps *leftSteps){
        // Bluetoohの診断を行います。
        RACSignal *signal = [self handleSignal:[self.service bluetoohCheckSignal:leftSteps] errorMsg:@"Bluetoothをオンにしてください。"];
        [self handleErrorSignal:signal];
        [[self commonSinal:signal stepNumber:leftSteps.stepNumber] subscribeNext:^(NSNumber *result) {
            self.hideMonitor = NO;
            [CheckResultUserDefaults standardUserDefaults].bluetoothCheckResult = [result integerValue];
        }];
    },/*^(Steps *leftSteps){
        // GPSセンサーの診断を行います。
        self.hideMonitor = NO;
        RACSignal *signal = [self handleSignal:[self.service gpsCheckSignal:leftSteps] errorMsg:@"位置情報サービスをオンにしてください。"];
        [self handleErrorSignal:signal];
        RAC(self, gpsString) = [self stringSinal:signal];
        [[self commonSinal:signal stepNumber:leftSteps.stepNumber] subscribeNext:^(NSNumber *result) {
            [CheckResultUserDefaults standardUserDefaults].gpsCheckResult = [result integerValue];
        }];
    },*/^(Steps *leftSteps){
        // ジャイロセンサーの診断を行います。
        RACSignal *signal = [self handleSignal:[self.service gyroCompassCheckSignal:leftSteps] errorMsg:nil];
        RAC(self, gyroString) = [self stringSinal:signal];
        [[self commonSinal:signal stepNumber:leftSteps.stepNumber] subscribeNext:^(NSNumber *result) {
            [CheckResultUserDefaults standardUserDefaults].compassCheckResult = [result integerValue];
        }];
    },^(Steps *leftSteps){
        // 磁気センサーの診断を行います。
        RACSignal *signal = [self handleSignal:[self.service magneticCheckSignal:leftSteps] errorMsg:@"位置情報サービスをオンにしてください。"];
        RAC(self, magneticString) = [self stringSinal:signal];
        [[self commonSinal:signal stepNumber:leftSteps.stepNumber] subscribeNext:^(NSNumber *result) {
            [CheckResultUserDefaults standardUserDefaults].magneticCheckResult = [result integerValue];
        }];
    },^(Steps *leftSteps){
        // 近接センサーの診断を行います。
        [[HUDHelper sharedInstance] showHUD:@"近接センサーの診断を行います。" message:@"画面の上に手をかざしてください。" yOffset:100];
        RACSignal *signal = [self handleSignal:[self.service proximityCheckSignal:leftSteps] errorMsg:nil];
        RAC(self, luminaString) = [self stringSinal:signal];
        [[self commonSinal:signal stepNumber:leftSteps.stepNumber] subscribeNext:^(NSNumber *result) {
            [[HUDHelper sharedInstance] hideHUD];
            [CheckResultUserDefaults standardUserDefaults].proximityCheckResult = [result integerValue];
        }];
    },^(Steps *leftSteps){
        // 輝度センサーの診断を行います。
        RACSignal *signal = [self handleSignal:[self.service luminaCheckSignal:leftSteps] errorMsg:nil];
        RAC(self, luminaString) = [self stringSinal:signal];
        [[self commonSinal:signal stepNumber:leftSteps.stepNumber] subscribeNext:^(NSNumber *result) {
            [CheckResultUserDefaults standardUserDefaults].luminaCheckResult = [result integerValue];
        }];
    },^(Steps *leftSteps){
        @strongify(self);
        self.hideMonitor = YES;
        self.checkCompleted = YES;
        // 自動診断は正常に終了しました。
        self.headerString = [self.itemsHeaderString lastObject];
    }]];
}

#pragma mark - commands

- (RACCommand *)recheckCommand
{
    if (!_recheckCommand) {
        @weakify(self);
        _recheckCommand = [[RACCommand alloc] initWithEnabled:[self checkCompletedSignal] signalBlock:^RACSignal *(id input) {
            @strongify(self);
            [self resetItemsResult];
            [self startCheck];
            return [RACSignal empty];
        }];
    }
    return _recheckCommand;
}

#pragma mark - signals

- (RACSignal *)multicastSignal:(RACSignal *)original
{
    RACMulticastConnection *connection = [original multicast:[RACReplaySubject subject]];
    [connection connect];
    return connection.signal;
}

- (RACSignal *)handleSignal:(RACSignal *)original errorMsg:(NSString*)message
{
    @weakify(self);
    RACSignal *checkSignal = [self multicastSignal:original];
    [checkSignal subscribeError:^(NSError *error) {
        @strongify(self);
        if (error) {
            [self showAlertWithString:[AutoCheckService messageWithError:error]];
        } else {
            [self showAlertWithString:message];
        }
    }];
    
    return checkSignal;
}

- (RACSignal *)resultSignal:(RACSignal *)common
{
    return [common filter:^BOOL(id value) {
        return [value isKindOfClass:[NSNumber class]];
    }];
}

- (RACSignal *)stringSinal:(RACSignal *)common
{
    return [common filter:^BOOL(id value) {
        return [value isKindOfClass:[NSString class]];
    }];
}

- (RACSignal *)errorSinal:(RACSignal *)common
{
    return [common filter:^BOOL(id value) {
        return [value isKindOfClass:[NSError class]];
    }];
}

- (void)handleErrorSignal:(RACSignal *)common
{
    [[self errorSinal:common] subscribeNext:^(NSError *error) {
        [self showAlertWithString:[AutoCheckService messageWithError:error]];
    }];
}

- (RACSignal *)commonSinal:(RACSignal *)signal stepNumber:(NSInteger)number
{
    @weakify(self);
    return [[self resultSignal:signal] doNext:^(NSNumber *result) {
        @strongify(self);
        [self.itemsResult replaceObjectAtIndex:number withObject:[CheckResultUserDefaults resultString:[result integerValue]]];
    }];
}

- (RACSignal *)checkCompletedSignal
{
    return [[RACObserve(self, checkCompleted) startWith:@(NO)] map:^id(id value) {
        return value;
    }];
}

#pragma mark - utils

- (void)showAlertWithString:(NSString *)message
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil
                                                    message:message
                                                   delegate:nil
                                          cancelButtonTitle:@"OK"
                                          otherButtonTitles:nil];
    [alert show];
}

- (void)resetItemsResult
{
    [self.itemsResult removeAllObjects];
    [self.items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        [self.itemsResult addObject:ITEM_RESULT_NO_CHECK];
    }];
}

@end

@implementation HUDHelper (CheckAutoItemViewModel)

- (void)showHUD:(NSString *)title message:(NSString *)message yOffset:(CGFloat)offset
{
    UIView *view = [[UIApplication sharedApplication].delegate window];
    CustomizedProgressHUD *hud = [CustomizedProgressHUD showHUDAddedTo:view animated:YES];
    hud.labelText = title;
    hud.detailsLabelText = message;
    hud.labelColor = [UIColor yellowColor];
    hud.detailsLabelColor = [UIColor yellowColor];
    hud.mode = MBProgressHUDModeText;
    hud.opacity = 0.6;
    hud.minSize = CGSizeMake(300, 44);
    CGFloat viewHeight = CGRectGetHeight(view.frame);
    CGFloat yPos0 = roundf((viewHeight - hud.minSize.height) / 2);
    hud.yOffset = offset-yPos0;
    
    hud.userInteractionEnabled = NO;
}

@end
